package com.dduggs.service;

import java.awt.AlphaComposite;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.RenderingHints;
import java.awt.geom.AffineTransform;
import java.awt.image.AffineTransformOp;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Map;
import java.util.UUID;

import javax.imageio.ImageIO;
import javax.swing.ImageIcon;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;


/**
 * @author CJS
 */
@Service
public class CommonFileService{

    private final Logger logger = LoggerFactory.getLogger(CommonFileService.class);

    private String waterImgPath = "";
    private String waterImgName = "image/watermark.png";
    private String filePath = "";

    public Map<String, String> upload(MultipartFile multiFile) throws Exception{

        //文件临时路径
        filePath = System.getProperty("catalina.home") + File.separator + "temp" + File.separator;
        logger.info("临时文件路径：" + filePath);
        waterImgPath = this.getClass().getResource("/").toString() + waterImgName;
        String fileName = multiFile.getOriginalFilename();
        String srcFileName = filePath + fileName;
        String targetFileName = filePath + System.currentTimeMillis() + "_" + fileName;

        this.saveFile(multiFile, filePath);

        if(fileName.toLowerCase().endsWith(".gif") || fileName.toLowerCase().endsWith(".jpeg") || fileName.toLowerCase().endsWith(".png")
                || fileName.toLowerCase().endsWith(".jpg") || fileName.toLowerCase().endsWith(".svg") || fileName.toLowerCase().endsWith(".bmp")){
            String imageFormat = fileName.substring(fileName.lastIndexOf(".") + 1, fileName.length());
            this.setPicWatermark(srcFileName, targetFileName, imageFormat);
        } else {
            throw new RuntimeException("GG");
        }

        File srcFile = new File(srcFileName);
        srcFile.delete();

        return null;
    }

    /**
     * 给图片添加水印图片
     *
     * @param srcImgPath
     *            源图片路径
     * @param targerPath
     *            目标图片路径
     */
    private void setPicWatermark(String srcImgPath, String targerPath, String imageFormat) throws Exception {
        OutputStream os = null;
        try {

            Image srcImg = ImageIO.read(new File(srcImgPath));

            BufferedImage buffImg = new BufferedImage(srcImg.getWidth(null),
                    srcImg.getHeight(null), BufferedImage.TYPE_INT_RGB);

            Graphics2D g = buffImg.createGraphics();

            g.setRenderingHint(RenderingHints.KEY_INTERPOLATION,
                    RenderingHints.VALUE_INTERPOLATION_BILINEAR);
            g.drawImage(srcImg.getScaledInstance(srcImg.getWidth(null), srcImg
                    .getHeight(null), Image.SCALE_SMOOTH), 0, 0, null);

            waterImgPath = waterImgPath.substring(5, waterImgPath.length());
            ImageIcon imgIcon = new ImageIcon(waterImgPath);

            Image img = imgIcon.getImage();

            if(imgIcon.getIconHeight() > buffImg.getHeight() || imgIcon.getIconWidth() > buffImg.getWidth()){
                //上传图片比水印图小，压缩水印图片
                String uuid = UUID.randomUUID().toString().replaceAll("-", "");
                String tmpWatermarkImgPath = filePath + System.currentTimeMillis() + "_" + uuid + ".png";
                this.resize(waterImgPath, tmpWatermarkImgPath, buffImg.getHeight(), buffImg.getWidth());
                BufferedImage bi = ImageIO.read(new File(tmpWatermarkImgPath));
                ImageIcon tmpImgIcon = new ImageIcon(tmpWatermarkImgPath);
                Image tmpImg = tmpImgIcon.getImage();
                g.drawImage(tmpImg, (buffImg.getWidth()-bi.getWidth())/2, (buffImg.getHeight()-bi.getHeight())/2, null);
                this.deleteFile(tmpWatermarkImgPath);
            } else {
                int left = (buffImg.getWidth() - (int)(buffImg.getWidth()/imgIcon.getIconWidth())*imgIcon.getIconWidth()) / 2;
                int bottom = (buffImg.getHeight() - (int)(buffImg.getHeight()/imgIcon.getIconHeight())*imgIcon.getIconHeight()) / 2;
                for (int height = imgIcon.getIconHeight(); height < buffImg.getHeight(); height = height + imgIcon.getIconHeight()) {
                    for (int weight = imgIcon.getIconWidth(); weight < buffImg.getWidth(); weight = weight + imgIcon.getIconWidth()) {
                        g.drawImage(img, left + weight - imgIcon.getIconWidth(), bottom + height - imgIcon.getIconHeight(), null);
                    }
                }
            }

            g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER));
            g.dispose();

            os = new FileOutputStream(targerPath);
            ImageIO.write(buffImg, imageFormat.toUpperCase(), os);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                if (null != os) {
                    os.close();
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    private void deleteFile(String fileName){
        File file = new File(fileName);
        if (file.exists() && file.isFile()) {
            file.delete();
        }
    }

    /**
     * 压缩图片
     * @throws IOException
     */
    private void resize(String filePath, String outFilePath, int height, int width) throws IOException {
        double ratio = 0; // 缩放比例
        File f = new File(filePath);
        File of = new File(outFilePath);
        BufferedImage bi = ImageIO.read(f);
        Image itemp = bi.getScaledInstance(width, height,
                BufferedImage.SCALE_SMOOTH);
        // 计算比例
        if ((bi.getHeight() > height) || (bi.getWidth() > width)) {
            if (height < width) {
                ratio = (new Integer(height)).doubleValue()
                        / bi.getHeight();
            } else {
                ratio = (new Integer(width)).doubleValue() / bi.getWidth();
            }
            AffineTransformOp op = new AffineTransformOp(
                    AffineTransform.getScaleInstance(ratio, ratio), null);
            itemp = op.filter(bi, null);
        }
        ImageIO.write((BufferedImage) itemp, "png", of);
    }

    private void saveFile(MultipartFile multiFile, String path) throws IOException{
        OutputStream os = null;
        InputStream inputStream = multiFile.getInputStream();
        try {
            byte[] bs = new byte[1024];
            int len;

            File tempFile = new File(path);
            if (!tempFile.exists()) {
                tempFile.mkdirs();
            }
            os = new FileOutputStream(tempFile.getPath() + File.separator + multiFile.getOriginalFilename());
            // 开始读取
            while ((len = inputStream.read(bs)) != -1) {
                os.write(bs, 0, len);
            }

        } catch (IOException e) {
            e.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            // 完毕，关闭所有链接
            try {
                os.close();
                inputStream.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

}
